import Vue from 'vue';


const db = uniCloud.databaseForJQL()
import permission from '../js_sdk/wa-permission/permission';
import setTabBar from '../utils/setTabBar';
import * as msgAction from '../utils/msgAction.js'
const linli = uniCloud.importObject('linliChat', {
	customUI: true
})
import {
	distanceNum
} from '../utils/distance';
import {
	getGridCode
} from '../utils/getSurroundingGrids';



export default {
	namespaced: true,
	state: {

		markers: [],
		user: {},
		sendUser: null,

		chatList: [],
		publicMessageList:[],
		currentSession: [],
		ws: null,
		reconnectTimer: null, // 存储定时器ID
		location: {}, // 接听位置
		senderLocation: {},
		locationMessage: [],
		count: 1, // 重连次数基数
		isFly: false,
		sessions: [],
		messageQueue: [],
		audioContext: null,
		joinGroup: null,
        backPageParams:{},
		stateConfig: {
			radius: 5,
			autoPlay:true,
		},

		isLocationResolved: false,
		toTarget: {},
		newMessage: {},
		onlineUserCount: 0,
		onlineShopCount: 0,
		address: {},
		mapScale: null,
		isLocationTimeout: false,
		unreadCount: 0,
		own: {},
		currentChatKey: '', //当前会话
		systemInfo: null,
		oldLoc: null,
		locationHandler: null,
		isLocationRunning: false,
		unreadCount: {
			key: '',
			count: 0
		},
		queryParam: {},
		locationMsgIntime: [] //周这边收到的消息

	},

	mutations: {
		// 修改 WebSocket 实例
		SET_WS(state, value) {
			Vue.set(state, 'ws', value);
		},

		SET_queryParam(state, value) {
			Vue.set(state, 'queryParam', value)
		},
		SET_SYSTEM_INFO(state, info) {
			state.systemInfo = info
		},
		SET_OLD_LOC(state, location) {
			state.oldLoc = location;
		},
		SET_toTarget(state, value) {
		
			Vue.set(state, 'toTarget', value)
		},
		updateUnreadCount(state, value) {
			Vue.set(state, 'unreadCount', value)
		},
		SET_backPageParams(state,value){
			Vue.set(state,'backPageParams',value)
		},
		// 更新监听状态
		SET_LOCATION_HANDLER(state, handler) {
	
			state.locationHandler = handler;
		},
		SET_IS_LOCATION_RESOLVED(state, val) {
			state.isLocationResolved = val;
		},
		SET_IS_LOCATION_RUNNING(state, status) {
			state.isLocationRunning = status;
		},
		SET_currentChatKey(state, status) {
			state.currentChatKey = status
		},
		SET_CHATLIST(state, value) {
			const newData = Array.isArray(value) ? value : [];
			state.chatList = [...newData];
			state.chatList.sort((a, b) => b.timestamp - a.timestamp);
		},
		// 修改定位信息
		SET_location(state, value) {

			Vue.set(state, 'location', value);
		},
		// 修改发送者位置
		SET_senderLocation(state, value) {
			
			Vue.set(state, 'senderLocation', value);
		},
        SET_own(state,value){
			Vue.set(state,'own',value)
		},
		// 修改用户信息
		SET_user(state, value) {
        
			Vue.set(state, 'user', value);
			

		},

	
		SET_publicMessageList(state, value) {

			state.publicMessageList = value
		},

		SET_newMessage(state, value) {
			Vue.set(state, 'newMessage', value)
		},
		SET_markers(state, value) {
			state.markers = value
		},
		SET_onlineUserCount(state, value) {
			state.onlineUserCount = value
		},
		SET_address(state, value) {
			
			Vue.set(state,'address',value)
		},
		SET_mapScale(state, value) {
			state.mapScale = value
		},
		SET_stateConfig(state,value){
			Vue.set(state, 'stateConfig',value)
		},
		SET_IS_LOCATION_RUNNING(state, status) {
			state.isLocationRunning = status;
		},
		SET_onlineShopCount(state, value) {
			state.onlineShopCount = value

		},
		// 修改飞行状态
		SET_isFly(state, value) {
			state.isFly = value;
		},
		SET_unreadCount(state,value){
			state.unreadCount=value
		},
		SET_messageQueue(state, value) {
		
			const newQueue = [...state.messageQueue, value]
			Vue.set(state, 'messageQueue', newQueue);
		
		},


		// 初始化本地存储数据
		INIT_STORAGE_DATA(state, storageData) {
			Object.keys(storageData).forEach(key => {
				if (state.hasOwnProperty(key)) {
					state[key] = storageData[key];
				}
			});
		
		},
		REPLACE_ALL_STATE(state, storageData) {
			if (!storageData || typeof storageData !== 'object') return;
			// 遍历 state 所有原有字段，用存储数据覆盖
			Object.keys(state).forEach(key => {
				// 仅更新 state 中已定义的字段，避免注入未知属性
				if (storageData.hasOwnProperty(key)) {
					// 复杂类型（对象/数组）用 Vue.set 确保响应式
					if (typeof storageData[key] === 'object' && storageData[key] !== null) {
						Vue.set(state, key, {
							...storageData[key]
						}); // 浅拷贝避免引用问题
					} else {
						Vue.set(state, key, storageData[key]);
					}
				}
			});
			console.log('state 已全部替换为本地存储数据');
		},


		// 记录重连延迟时间（不启动定时器，仅存状态）
		scheduleReconnect(state) {
			if (state.reconnectTimer) return;
			const delay = Math.min(2 ** state.count * 1000, 8000); // 指数退避重连
			state.reconnectTimer = delay;
		},
		// 清除重连定时器
		clearReconnectTimer(state) {
			if (state.reconnectTimer) {
				clearTimeout(state.reconnectTimer);
				state.reconnectTimer = null;
			}
		},
		// 关闭已存在的WebSocket连接
		closeExistingWebSocket(state) {
			if (state.ws) {
				uni.closeSocket();
				state.ws = null;
			}
		},
		// 更新重连次数
		SET_COUNT(state, value) {
			state.count = value;
		},
		SET_IS_LOCATION_TIMEOUT(state, val) {
			state.isLocationTimeout = val;
		},
		// 记录定时器ID（新增）
		SET_RECONNECT_TIMER(state, timerId) {
			state.reconnectTimer = timerId;
		},
		// 更新加入群组信息
		SET_JOIN_GROUP(state, data) {
			state.joinGroup = data;
		},

		SET_stateConfig(state, data) {

			Vue.set(state, 'stateConfig', data)
		},
		SET_ws(state, data) {
			state.ws = data

		}
	},

	actions: {

		async getSystemInfo({
			commit
		}) {
			try {
				// 调用 uni.getSystemInfoSync() 同步获取（或用异步方法）
				const res = await uni.getSystemInfo()
				commit('SET_SYSTEM_INFO', res[1])

			} catch (error) {
				console.error('获取系统信息失败：', error)
			}

		},
		async replaceStateFromStorage({
			commit
		}) {
			try {
				// 读取本地存储的完整 state 数据（假设存储键为 'msgDataStore'）
				const storageData = uni.getStorageSync('msgDataStore');
				if (!storageData || Object.keys(storageData).length === 0) {
					console.warn('本地存储无 state 数据，无需替换');
					return false;
				}
				// 触发 mutation 替换所有 state
				commit('REPLACE_ALL_STATE', storageData);
				return true;
			} catch (error) {
				console.error('替换 state 失败：', error);
				uni.showToast({
					title: '数据恢复失败',
					icon: 'none',
					duration: 2000
				});
				return false;
			}
		},
		saveStateToStorage({
			state
		}) {
			try {
				// 深拷贝 state（避免直接引用导致存储异常，处理复杂类型）
				const stateToSave = JSON.parse(JSON.stringify(state));
				// 存储到本地（键名与之前读取的一致：msgDataStore）
				uni.setStorageSync('msgDataStore', stateToSave);
				console.log('state 已成功保存到本地存储');
			} catch (error) {
				console.error('保存 state 到本地失败：', error);
				// 可选：仅在调试模式显示错误提示，避免干扰用户
				if (getApp().globalData.debug) {
					uni.showToast({
						title: '数据保存失败',
						icon: 'none'
					});
				}
			}
		},
		async setConfig({state}){
		const res=await	linli.setConfig(state.user.userId,state.stateConfig)
		if(res){
			uni.showToast({
				title:'已保存配置',
				position:'center'
			})
		}
		},
		
		async getUserInfo({
			commit,
			state
		}) {
			try {
				// 关键修正：添加 .get() 方法执行查询
				const userTel = uni.getStorageSync('userTel');
				if (!userTel) throw new Error('用户手机号不存在')
				const res = await db.collection('linli-user').where({
					userTel: userTel // 筛选条件：匹配当前用户的userId
				}).get(); // 必须调用 get() 才会执行查询请求

				// 检查查询结果是否存在
				if (res.data && res.data.length > 0) {
					commit('SET_user', res.data[0]); // 将查询到的用户信息存入状态
					commit('SET_stateConfig', res.data[0].stateConfig)

				} else {

					commit('SET_user', null); // 或设置默认空对象
				}
			} catch (e) {
				console.error('查询用户信息失败:', e.message);
				// 可添加错误提示（如通过uni.showToast）
				uni.showToast({
					title: '获取用户信息失败',
					icon: 'none',
					duration: 2000
				});
			}
		},

		async initializeChatList({
			commit,
			state
		}) { // 从参数中解构 state
			try {
			const data = await initializeData();
				commit('SET_CHATLIST', data);
			} catch (error) {
				console.error("initializeChatList 执行失败:", error); // 捕获所有可能的错误
			}
		},
	async	setupWebSocketListeners({
			commit,
			state,
			dispatch
		}) {
			uni.onSocketOpen(() => {
				console.warn('WebSocket连接已打开', state.ws);
				commit('SET_COUNT', 1); // 重置重连次数
				uni.$emit('onlineStatusChanged', true);
				// 连接成功后可处理消息队列
				dispatch('processMessageQueue');
			});

			// 连接关闭回调
			uni.onSocketClose((res) => {
				console.log('WebSocket连接关闭:', res);
				uni.$emit('onlineStatusChanged', false);
				commit('scheduleReconnect'); // 触发重连计划（仅记录延迟）
				dispatch('startReconnectTimer'); // 启动重连定时器
			});

			// 连接错误回调
			uni.onSocketError((error) => {
				console.error('WebSocket连接错误:', error);
				uni.$emit('onlineStatusChanged', false);
				commit('scheduleReconnect');
				dispatch('startReconnectTimer');
			});

			// 接收消息回调
			uni.onSocketMessage(async (msg) => {
				try {
					const msgJsoned = JSON.parse(msg.data);
			         console.log("接收到新消息",msgJsoned);

					switch (msgJsoned.type) {
						case 'joinGroup':
							commit('SET_JOIN_GROUP', msgJsoned);
							uni.$emit('joinGroup', msgJsoned);
							break;
						case 'msg':
							if (msgJsoned.data.length > 0) {

								msgJsoned.data.map((msg) => {
									console.log('远端接收到消息', msg);
									msgAction.receivMsg(msg)
								})

								// uni.$emit('readmessages', msgJsoned.data);
								// const msg = await processReceivedMessage(msgJsoned.data, state.user)

								// commit('SET_CHATLIST', msg);
								// typeofMsg(msgJsoned.data)

							}

							break;
						case 'onLine':

							uni.$emit('onLineNoti', msgJsoned);
							break;
						default:
							break;
					}
				} catch (e) {
					console.error('解析WebSocket消息失败:', e);
				}
			});
		},



		//位置获取及权限判断（关键方法）
		async getLocation({
			commit,
			state,
			dispatch
		}) {

			await dispatch('stopLocationUpdate');
			commit('SET_IS_LOCATION_RESOLVED', false);
			commit('SET_IS_LOCATION_TIMEOUT', false);
			commit('SET_IS_LOCATION_RUNNING', true); // 新增：设置运行状态

			return new Promise(async (resolve, reject) => {
				try {
					const {
						model
					} = uni.getSystemInfoSync();
					// 模拟器调试模式
					if (getApp().globalData.debug && model === 'BRA-AL00') {
						const location = {
							latitude: 26.042691129986203,
							longitude: 119.21654665710264
						};
						commit('SET_senderLocation', location);
						commit('SET_location', location);
						resolve(location);
						return;
					}

					// 正式模式：权限校验
					console.warn('定位开始。。。·1');
					const isSystemLocEnabled = permission.checkSystemEnableLocation();
					if (!isSystemLocEnabled) throw new Error('请先开启系统定位服务（设置-定位服务）');
					const hasPermission = await dispatch('checkAndRequestPermission');
					if (!hasPermission) throw new Error('定位权限未授权，无法使用核心功能');

					// 定位监听函数（添加三重过滤）
					const locationHandler = async (location) => {
						uni.$emit('locationChange',location)
				
						
						// 关键过滤：已resolve/已超时/未运行，直接返回不执行
						if ( state.isLocationTimeout || !state
							.isLocationRunning) {
							console.warn('定位回调被过滤', {
								resolved: state.isLocationResolved,
								timeout: state.isLocationTimeout,
								running: state.isLocationRunning
							});


							return;
						}
						try {

							if (!state.isLocationResolved) {

								commit('SET_OLD_LOC', location);
								commit('SET_location', location);
								commit('SET_senderLocation', location);

						
								// 标记已成功，停止定位，返回结果
								commit('SET_IS_LOCATION_RESOLVED', true);
								resolve(location);
						
								
								return;
							}

							// 后续位置变化（仅首次resolve后执行，距离>0.01才更新）
							try {
							
								if (distanceNum(location, state.oldLoc) > 0.01) {
									if (!state.isFly) commit('SET_location', location);
									uni.$emit('senderlocation', {
										longitude: location.longitude,
										latitude: location.latitude
									});

									commit('SET_senderLocation', location);
									commit('SET_OLD_LOC', location);
							
								}
							} catch (err) {
										console.error('定位停止');
								console.error('位置计算失败：', err);
							}
						} catch (err) {
							console.error('定位数据处理失败：', err);
							if (!state.isLocationResolved) {
								reject(err);
								await dispatch('stopLocationUpdate');
								console.error('定位停止');
							}
						}
					};

					// 存储监听函数，启动定位
					commit('SET_LOCATION_HANDLER', locationHandler);
					await dispatch('startLocationUpdate');
				
					// 10秒超时兜底（核心修复：避免无限等待）
					setTimeout(() => {
						if (!state.isLocationResolved) {
							commit('SET_IS_LOCATION_TIMEOUT', true);
							dispatch('stopLocationUpdate').then(() => {
								reject(new Error('定位超时，请检查网络和定位信号'));
							}).catch(err => {
								console.error('超时后停止定位失败：', err);
								reject(err);
							});
						}
					}, 10000);

				} catch (err) {
					commit('SET_IS_LOCATION_RUNNING', false)
					console.error('定位初始化失败：', err);
					reject(err);
					// 初始化失败也停止定位，避免残留
					dispatch('stopLocationUpdate').catch(err2 => console.error('初始化失败后停止定位失败：', err2));
							
				}
			});
		},

		// 检查并申请定位权限
		async checkAndRequestPermission({
			state
		}) {
			const {
				platform
			} = uni.getSystemInfoSync();
			if (platform === 'android') {
				const result = await permission.requestAndroidPermission('android.permission.ACCESS_FINE_LOCATION');
				if (result === -1) { // 永久拒绝
					uni.showModal({
						title: '定位权限被永久拒绝',
						content: '请在设置中手动开启定位权限',
						confirmText: '去设置',
						showCancel: false,
						success: () => permission.gotoAppPermissionSetting()
					});
				}
				return result === 1;
			} else if (platform === 'ios') {
				let isAuth = permission.judgeIosPermission('location');
				if (!isAuth) {
					isAuth = await new Promise(resolve => {
						uni.authorize({
							scope: 'scope.userLocation',
							success: () => resolve(true),
							fail: (err) => {
								console.error('iOS 授权失败：', err);
								// 引导至设置页
								uni.showModal({
									title: '需要定位权限',
									content: '请在iPhone设置中开启本App的定位权限',
									confirmText: '去设置',
									showCancel: false,
									success: () => permission.gotoAppPermissionSetting()
								});
								resolve(false);
							}
						});
					});
				}
				return isAuth;
			}
			return false;
		},




		async startLocationUpdate({
			commit,
			state
		}) {
			if (!state.locationHandler) {
				console.log('没有定位回调函数');
				return;
			}

			try {
				uni.onLocationChange(state.locationHandler);
				await uni.startLocationUpdate({
					fail: (err) => {
						commit('SET_IS_LOCATION_RUNNING', false); // 启动失败时重置状态
						if (err.errMsg.includes('permission')) {
							throw new Error('定位权限已被关闭，请重新授权');
						} else {
							throw new Error(`定位服务启动失败：${err.errMsg}，请检查定位服务是否开启`);
						}
					}
				});
				// 启动成功，状态已在 getLocation 中设置
			} catch (err) {
				commit('SET_IS_LOCATION_RUNNING', false); // 异常时重置状态
				if (state.locationHandler) {
					uni.offLocationChange(state.locationHandler);
					commit('SET_LOCATION_HANDLER', null);
				}
				console.error('启动定位失败：', err);
				throw err;
			}
		},
		async stopLocationUpdate({
			commit,
			state
		}) {
			try {
				commit('SET_IS_LOCATION_RUNNING', false); // 先停止运行状态

				if (!state.locationHandler) return;
				await uni.stopLocationUpdate();
				uni.offLocationChange(state.locationHandler);
				commit('SET_LOCATION_HANDLER', null);

				console.warn('定位监听已停止，状态已重置');
			} catch (err) {
				commit('SET_IS_LOCATION_RUNNING', false); // 确保异常时也重置状态
				commit('SET_LOCATION_HANDLER', null);
				console.error('停止定位失败：', err);
			}
		},



		// 启动重连定时器
		startReconnectTimer({
			commit,
			state,
			dispatch
		}) {
		
			// 若已有定时器，先清除
			if (typeof state.reconnectTimer === 'number') {
				clearTimeout(state.reconnectTimer);
			}
			// 从state获取延迟时间（由scheduleReconnect设置）
			const timer = setTimeout(() => {
				dispatch('reconnect'); // 执行重连
				commit('SET_COUNT', state.count + 1); // 递增重连次数
			}, state.reconnectTimer);
			commit('SET_RECONNECT_TIMER', timer); // 记录定时器ID
		},


		// 建立WebSocket连接
		async connectWebSocket({
			commit,
			dispatch
		}, {
			location,
			userTel
		}) {
			// 前置清理
			commit('clearReconnectTimer');
			commit('closeExistingWebSocket');
			console.log('连接中。。。。');
			const query = {
				userTel: userTel,
				location: JSON.stringify(location)
			};

			try {
				const ws = await uniCloud.connectWebSocket({
					name: 'web',
					query: query
				});
				commit('SET_WS', ws); // 保存WebSocket实例
				console.log('已连接');
				dispatch('setupWebSocketListeners'); // 注册监听器（用dispatch调用action）
				return true;
			} catch (error) {
				console.error('WebSocket连接失败:', error);
				uni.showToast({
					title: '网络故障，无法连接',
					icon: 'error'
				});
				return false;
			}
		},

		// 重连WebSocket
		async reconnect({
			state,
			dispatch
		}) {

			// 1. 容错：处理 ws 为 null/undefined 的情况
			const ws = state.ws;
			const isConnected = ws && ws.readyState === 1; // 仅当 ws 存在且状态为连接中（1）时，视为已连接

			// 2. 若已连接，或缺少必要参数（位置/用户手机号），则不重连
			if (isConnected || !state.location || !state.user?.userTel) {
				console.log('不执行重连：已连接或参数不全');

				return;
			}

			// 3. 执行重连（先关闭可能存在的旧连接，避免残留）
			try {
				// 若存在未关闭的旧连接，先手动关闭
				if (ws && [0, 2, 3].includes(ws.readyState)) { // 0:连接中, 2:正在关闭, 3:已关闭
					ws.close();
					console.log('关闭旧的WebSocket连接');
				}

				// 调用连接方法
				await dispatch('connectWebSocket', {
					location: state.location,
					userTel: state.user.userTel
				});
				console.log('WebSocket重连成功');
			} catch (error) {
				console.error('WebSocket重连失败：', error);
				// 可选：添加重试机制（如3次重试）
				// throw error; // 若需要上层捕获，可抛出错误
			}
		},

		// 处理消息队列（连接成功后发送缓存的消息）
		processMessageQueue({
			state
		}) {
			if (state.messageQueue.length === 0 || state.ws.readyState !== 1) return;
	
			// 遍历发送队列中的消息
			state.messageQueue.forEach(msg => {
				state.ws.send({
					data: JSON.stringify(msg)
				});
			});
			// 清空队列
			state.messageQueue = [];


		},

	},
	getters: {
		getConfig(state){
			return state.user.stateConfig
		},
		currentSession(state) {
			
			const unreadList = state.chatList.filter(item => item.unreadCount > 0);

},




		isfly(state) {

			return getGridCode(state.location) !== getGridCode(state.senderLocation)
		},
		getUnreadMsg: state => state.unreadCount || 0, //这是区域信息未读信息
		getCurrentSessionCount(state) {
			const unreadList = state.chatList.filter(item => item.unreadCount > 0);

			if (unreadList.length > 0) {
				const unreads = unreadList.sort((a, b) => b.timestamp - a.timestamp);
				const count = unreads.reduce((sum, item) => {
					const unread = typeof item.unreadCount === 'number' ? item.unreadCount : 0;
					return sum + Math.max(0, unread);
				}, 0);

				return count

			}
		}


}

	
}